home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 June: Reference Library / Dev.CD Jun 96 RL / Dev.CD Jun 96 RL.toast / Technical Documentation / develop / develop Issue 26 / develop Issue 26 code / Truffles - Display Mgr. / Sprocket / ExperimentalStuff / UAppleObject.cp < prev    next >
Encoding:
Text File  |  1995-12-10  |  13.2 KB  |  594 lines  |  [TEXT/MMCC]

  1. // UAppleObject.cp
  2. // by Eric Berdahl
  3. // AppleLink: BERDAHL
  4. // Interget: eric_berdahl@taligent.com
  5. // May XX, 1992
  6. //
  7. // Copyright © 1992 Eric M. Berdahl
  8. // All rights reserved.
  9. //
  10. // LICENSE
  11. //
  12. // UAppleObject is provided under the ego-ware™ system.  If you send me a note
  13. // telling me how cool you think it UAppleObject is, you may incorporate it into
  14. // any product you like (six-packs of good beer are also acceptable, no C.O.D.
  15. // shipments, please).  Also, you must keep all copyright and other notices in
  16. // the source code, especially MY NAME (The system is called ego-ware™.  Get it?).
  17.  
  18.  
  19. #ifndef __AEOBJECTS__
  20. #include <AEObjects.h>
  21. #endif
  22.  
  23. #ifndef    __EXCEPTIONS__
  24. #include "Exceptions.h"
  25. #endif
  26.  
  27. #ifndef __RESOURCES__
  28. #include <Resources.h>
  29. #endif
  30.  
  31. #ifndef _UAPPLEOBJECT_
  32. #include "UAppleObject.h"
  33. #endif
  34.  
  35.  
  36. // This unit requires a definition for DEBUG (indicating whether or not you
  37. // want debugging code compiled in).  If you don’t set the flag, I’ll just 
  38. // assume you don’t want any.
  39. #ifndef DEBUG
  40. #define    DEBUG 0
  41. #endif
  42.  
  43. //--------------------------------------------------------------------------------
  44. // TAppleObjectDispatcher
  45. //--------------------------------------------------------------------------------
  46.  
  47. TAppleObjectDispatcher* TAppleObjectDispatcher::fgDispatcher = nil;
  48. Boolean TAppleObjectDispatcher::fgInited = false;
  49.  
  50.  
  51. TAppleObjectDispatcher::TAppleObjectDispatcher()
  52. {
  53.     fDisposalList = nil;
  54.     fDisposalListSize = 0;
  55.     fApplication = nil;
  56. }
  57.  
  58.  
  59. TAppleObjectDispatcher::~TAppleObjectDispatcher()
  60. {
  61.     if (fDisposalList != nil)
  62.         DisposeHandle((Handle) fDisposalList);
  63. }
  64.  
  65. struct MAEventTableRec
  66. {
  67.     OSType theClass;
  68.     OSType theID;
  69.     long theValue;
  70. };
  71. typedef MAEventTableRec* MAEventTablePointer;
  72.  
  73. void TAppleObjectDispatcher::Install()
  74. {
  75.     if (fgDispatcher != nil)
  76.         FailOSErr(errAppleObjectDispatcherAlreadyInstalled);
  77.  
  78.     Try
  79.     {
  80.         if (!fgInited)
  81.         {
  82.             AEObjectInit();
  83.             fgInited = true;
  84.         }
  85.  
  86.         fgDispatcher = this;
  87.  
  88.         // Install AppleEvent handlers from all aedt resources
  89.         // Look for all AppleEvent dispatch tables… 
  90.         short numberOfTables = Count1Resources('aedt');
  91.         FailResError();
  92.  
  93.         for (short tableIndex = 1; tableIndex <= numberOfTables; ++tableIndex)
  94.         {
  95.             Handle tableHandle = Get1IndResource('aedt', tableIndex);
  96.             
  97.             Try
  98.             {
  99.                 FailResError();
  100.  
  101.                 SignedByte savedState = HGetState(tableHandle);
  102.                 HLockHi(tableHandle);
  103.  
  104.                 long tableSize = GetHandleSize(tableHandle);
  105.                 FailMemError();
  106.  
  107.                 short tableElements = (short)(tableSize / sizeof(MAEventTableRec));
  108.  
  109.                 MAEventTablePointer tablePtr = (MAEventTablePointer) *tableHandle;
  110.  
  111.                 // Install a single event handler for all events 
  112.                 for (short eventIndex = 1; eventIndex <= tableElements; ++eventIndex, ++tablePtr)
  113.                     this->InstallAppleEventHandler(tablePtr->theClass, tablePtr->theID, tablePtr->theValue);
  114.  
  115.                 HSetState(tableHandle, savedState);
  116.             }
  117.             Catch(err)
  118.             {
  119.                 if (tableHandle)
  120.                     ReleaseResource(tableHandle);
  121.                 Throw(err);
  122.             }
  123.  
  124.             ReleaseResource(tableHandle);
  125.         }
  126.  
  127.  
  128.  
  129.  
  130.             // Install a universal object accessor
  131.         FailOSErr(AEInstallObjectAccessor(typeWildCard, typeWildCard,
  132.                                    NewOSLAccessorProc(TAppleObjectDispatcher::OSLObjectAccessorHandler),
  133.                                    0, false));
  134.  
  135.             // Set up the object support library callbacks
  136.         FailOSErr(AESetObjectCallbacks(
  137.                             NewOSLCompareProc(TAppleObjectDispatcher::OSLCompareObjectsHandler),
  138.                             NewOSLCountProc(TAppleObjectDispatcher::OSLCountObjectsHandler),
  139.                             NewOSLDisposeTokenProc(TAppleObjectDispatcher::OSLDisposeTokenHandler),    
  140.                             nil, nil, nil, nil));
  141.     }
  142.     Catch(err)
  143.     {
  144.         fgDispatcher = nil;
  145.         Throw(err);
  146.     }
  147. }
  148.  
  149.  
  150. MAppleObject* TAppleObjectDispatcher::ExtractObject(const AEDesc& descriptor)
  151. {
  152.     MAppleObject* result;
  153.  
  154.     if (descriptor.descriptorType == typeNull)
  155.         result = MAppleObject::GetDefaultAppleObject();
  156.     else
  157.         result = (MAppleObject*)descriptor.dataHandle;
  158.  
  159. #if DEBUG
  160.         if (descriptor.descriptorType != result->GetAppleClass())
  161.             DebugStr((ConstStr255Param) "Protocol error: object isn’t what it says it is");
  162. #endif
  163.  
  164.     return result;
  165. }
  166.  
  167.  
  168. MAppleObject* TAppleObjectDispatcher::GetTarget(const AppleEvent& message)
  169. {
  170.     // The target defaults to the application
  171.     MAppleObject* result = MAppleObject::GetDefaultAppleObject();
  172.  
  173.     Try
  174.     {
  175.         AEDesc    theDirectParameter;
  176.         FailOSErr(AEGetParamDesc(&message, keyDirectObject, typeWildCard, &theDirectParameter));
  177.         Try
  178.         {
  179.             // If the direct object is an object specifier, resolve it into
  180.             // an application domain object.
  181.             if (theDirectParameter.descriptorType == typeObjectSpecifier)
  182.                 result = this->ResolveSpecifier(theDirectParameter);
  183.         }
  184.         Catch(err)
  185.         {
  186.             OSErr ignoreErr = AEDisposeDesc(&theDirectParameter);
  187.             Throw(err);
  188.         }
  189.     }
  190.     Catch(err)
  191.     {
  192.         // It’s all right for there to be no direct object.  In that
  193.         // case, we stick with the default.
  194.         if (err != errAEDescNotFound)
  195.             Throw(err);
  196.     }
  197.  
  198. NoDescriptor:
  199.     FailNIL(result);
  200.  
  201.     return result;
  202. }
  203.  
  204.  
  205. void TAppleObjectDispatcher::StuffDescriptor(AEDesc& descriptor,
  206.                                              MAppleObject* object)
  207. {
  208.     descriptor.descriptorType = object->GetAppleClass();
  209.     descriptor.dataHandle = (Handle) object;
  210. }
  211.  
  212.  
  213. void TAppleObjectDispatcher::HandleAppleEvent(const AppleEvent& message,
  214.                                   AppleEvent& reply,
  215.                                   long refCon)
  216. {
  217.     MAppleObject* theTarget = this->GetTarget(message);
  218.     theTarget->DoAppleEvent(message, reply, refCon);
  219.  
  220.     // Dispose of the token object
  221.     AEDesc    fakeToken;
  222.     this->StuffDescriptor(fakeToken, theTarget);
  223.     FailOSErr(AEDisposeToken(&fakeToken));
  224. }
  225.  
  226.  
  227. void TAppleObjectDispatcher::AccessContainedObjects(DescType desiredClass,
  228.                                         const AEDesc& container,
  229.                                         DescType containerClass,
  230.                                         DescType form,
  231.                                         const AEDesc& selectionData,
  232.                                         AEDesc& value,
  233.                                         long /* refCon */)
  234. {
  235.     MAppleObject* containerObject = this->ExtractObject(container);
  236.  
  237. #if DEBUG
  238.         if (containerObject->GetAppleClass() != containerClass)
  239.             DebugStr((ConstStr255Param) "Protocol error: object isn’t what the AE Manager thinks it is");
  240. #endif
  241.  
  242.     Boolean    needsDisposal;
  243.     MAppleObject* resultObject = containerObject->GetContainedObject(desiredClass,
  244.                                                         form, selectionData,
  245.                                                         needsDisposal);
  246.     if (resultObject == nil)
  247.         FailOSErr(errAENoSuchObject);
  248.  
  249.     this->StuffDescriptor(value, resultObject);
  250.  
  251.     if (needsDisposal)
  252.         this->SetTokenObjectDisposal(resultObject, true);
  253. }
  254.  
  255.  
  256. long TAppleObjectDispatcher::CountObjects(const AEDesc& containerToken,
  257.                               DescType countObjectsOfType)
  258. {
  259.     MAppleObject* containerObject = this->ExtractObject(containerToken);
  260.     return containerObject->CountContainedObjects(countObjectsOfType);
  261. }
  262.  
  263. Boolean TAppleObjectDispatcher::CompareObjects(DescType operation,
  264.                                                const AEDesc& obj1,
  265.                                                const AEDesc& obj2)
  266. {
  267.     MAppleObject*    mObj1 = this->ExtractObject(obj1);
  268.     MAppleObject*    mObj2 = this->ExtractObject(obj2);
  269.  
  270.     return mObj1->CompareAppleObjects(operation, *mObj2);
  271. }
  272.  
  273. void TAppleObjectDispatcher::DisposeToken(AEDesc& unneededToken)
  274. {
  275.     MAppleObject*    theObject = this->ExtractObject(unneededToken);
  276.     if (this->GetTokenObjectDisposal(theObject))
  277.         delete theObject;
  278. }
  279.  
  280.  
  281. Boolean TAppleObjectDispatcher::GetTokenObjectDisposal(const MAppleObject* theObject)
  282. {
  283.     Boolean    result = false;
  284.  
  285.     // Search the list of objects to be disposed.  Return true if the object is
  286.     // in the list.
  287.     MAppleObject** curObj = *fDisposalList;
  288.     for (long i = 0; i < fDisposalListSize; i++, curObj++)
  289.     {
  290.         if (theObject == *curObj)
  291.         {
  292.             result = true;
  293.             break;
  294.         }
  295.     }
  296.  
  297.     return result;
  298. }
  299.  
  300.  
  301. void TAppleObjectDispatcher::SetTokenObjectDisposal(MAppleObject* theObject,
  302.                                                Boolean needsDisposal)
  303. {
  304.     // Search the list of objects to be disposed to see if it currently exists.
  305.     Boolean nilFound = false;
  306.     Boolean    found = false;
  307.     MAppleObject** curObj = *fDisposalList;
  308.     for (long i = 0; i < fDisposalListSize; i++, curObj++)
  309.     {
  310.         if (theObject == *curObj)
  311.         {
  312.             found = true;
  313.  
  314.             if (!needsDisposal)
  315.                 // remove it from the disposal list
  316.                 *curObj = nil;
  317.  
  318.             break;
  319.         }
  320.         else if (*curObj == nil)
  321.             nilFound = true;
  322.     }
  323.  
  324.     if (!found  &&  needsDisposal)
  325.     {
  326.         // it needs to be added to the list
  327.  
  328.         if (nilFound)
  329.         {
  330.             // we can sneak into a nil spot
  331.             curObj = *fDisposalList;
  332.             for (long i = 0; i < fDisposalListSize; i++, curObj++)
  333.             {
  334.                 if (*curObj == nil)
  335.                 {
  336.                     *curObj = theObject;
  337.                     break;
  338.                 }
  339.             }
  340.         }
  341.         else
  342.         {
  343.             // If the list hasn’t been created yet, create a zero-sized list
  344.             if (fDisposalList == nil)
  345.             {
  346.                 fDisposalList = (MAppleObject***) NewHandle(0);
  347.                 FailNIL(fDisposalList);
  348.             }
  349.  
  350.             Try
  351.             {
  352.                 fDisposalListSize++;
  353.                 SetHandleSize((Handle) fDisposalList, fDisposalListSize*sizeof(MAppleObject*));
  354.                 FailMemError();
  355.                 curObj = *fDisposalList;
  356.                 curObj += fDisposalListSize - 1;
  357.                 *curObj = theObject;
  358.             }
  359.             Catch(err)
  360.             {
  361.                 fDisposalListSize--;
  362.                 Throw(err);
  363.             }
  364.         }
  365.     }
  366. }
  367.  
  368.  
  369. MAppleObject* TAppleObjectDispatcher::ResolveSpecifier(AEDesc& objectSpecifier)
  370. {
  371.     AEDesc    tokenDesc;
  372.     FailOSErr(AEResolve(&objectSpecifier, kAEIDoMinimum, &tokenDesc));
  373.     MAppleObject* result = this->ExtractObject(tokenDesc);
  374.     return result;
  375. }
  376.  
  377.  
  378. pascal OSErr TAppleObjectDispatcher::AppleEventHandler(const AppleEvent* message,
  379.                                           AppleEvent* reply,
  380.                                           long refCon)
  381. {
  382.     OSErr    result = noErr;
  383.  
  384.     Try
  385.     {
  386.         GetDispatcher()->HandleAppleEvent(*message, *reply, refCon);
  387.     }
  388.     Catch(err)
  389.     {
  390.         result = err;
  391.     }
  392.  
  393.     return result;
  394. }
  395.  
  396. pascal OSErr TAppleObjectDispatcher::OSLObjectAccessorHandler(DescType desiredClass,
  397.                                          const AEDesc* container,
  398.                                          DescType containerClass,
  399.                                          DescType form,
  400.                                          const AEDesc* selectionData,
  401.                                          AEDesc* value,
  402.                                          long refCon)
  403. {
  404.     OSErr    result = noErr;
  405.  
  406.     Try
  407.     {
  408.         GetDispatcher()->AccessContainedObjects(desiredClass, *container,
  409.                                                 containerClass, form,
  410.                                                 *selectionData,
  411.                                                 *value, refCon);
  412.     }
  413.     Catch(err)
  414.     {
  415.         result = err;
  416.     }
  417.  
  418.     return result;
  419. }
  420.  
  421. pascal OSErr TAppleObjectDispatcher::OSLCountObjectsHandler(DescType countObjectsOfType,
  422.                                             DescType /* containerClass */,
  423.                                             const AEDesc* containerToken,
  424.                                             long* result)
  425. {
  426.     OSErr    theErr = noErr;
  427.  
  428.     Try
  429.     {
  430.         *result = GetDispatcher()->CountObjects(*containerToken, countObjectsOfType);
  431.     }
  432.     Catch(err)
  433.     {
  434.         theErr = err;
  435.     }
  436.  
  437.     return theErr;
  438. }
  439.  
  440.  
  441. pascal OSErr TAppleObjectDispatcher::OSLCompareObjectsHandler(DescType operation,
  442.                                          const AEDesc *obj1,
  443.                                          const AEDesc *obj2,
  444.                                          Boolean *answer)
  445. {
  446.     OSErr    result = noErr;
  447.  
  448.     Try
  449.     {
  450.         *answer = GetDispatcher()->CompareObjects(operation, *obj1, *obj2);
  451.     }
  452.     Catch(err)
  453.     {
  454.         result = err;
  455.     }
  456.  
  457.     return result;
  458. }
  459.  
  460.  
  461. pascal OSErr TAppleObjectDispatcher::OSLDisposeTokenHandler(AEDesc* unneededToken)
  462. {
  463.     OSErr    result = noErr;
  464.  
  465.     Try
  466.     {
  467.         GetDispatcher()->DisposeToken(*unneededToken);
  468.     }
  469.     Catch(err)
  470.     {
  471.         result = err;
  472.     }
  473.  
  474.     return result;
  475. }
  476.  
  477.  
  478. void TAppleObjectDispatcher::InstallAppleEventHandler(AEEventClass theClass,
  479.                                                      AEEventID theID,
  480.                                                      long refCon)
  481. {
  482.     FailOSErr(AEInstallEventHandler(theClass, theID,
  483.                                     NewAEEventHandlerProc(TAppleObjectDispatcher::AppleEventHandler),
  484.                                     refCon, false));
  485. }
  486.  
  487.  
  488. //--------------------------------------------------------------------------------
  489. // MAppleObject
  490. //--------------------------------------------------------------------------------
  491.  
  492. Boolean MAppleObject::fgInited = false;
  493. MAppleObject* MAppleObject::fgDefaultAppleObject = nil;
  494.  
  495.  
  496. MAppleObject::MAppleObject()
  497. {
  498. }
  499.  
  500.  
  501. MAppleObject::MAppleObject(const MAppleObject& /* copy */)
  502. {
  503. }
  504.  
  505.  
  506. MAppleObject::~MAppleObject()
  507. {
  508.     if (MAppleObject::GetDefaultAppleObject() == this)
  509.         MAppleObject::SetDefaultAppleObject(nil);
  510.  
  511.     TAppleObjectDispatcher::GetDispatcher()->SetTokenObjectDisposal(this, false);
  512. }
  513.  
  514.  
  515. MAppleObject& MAppleObject::operator=(const MAppleObject& /* assignTo */)
  516. {
  517.     return *this;
  518. }
  519.  
  520.  
  521. void MAppleObject::InitAppleObject(TAppleObjectDispatcher* dispatcher)
  522. {
  523.     // create a dispatcher if one wasn't passed in
  524.     if (dispatcher == nil)
  525.     {
  526.         dispatcher = new TAppleObjectDispatcher();
  527.         FailNIL(dispatcher);
  528.     }
  529.  
  530.     // Install the dispatcher
  531.     dispatcher->Install();
  532.  
  533.     fgInited = true;
  534. }
  535.  
  536.  
  537. long MAppleObject::CountContainedObjects(DescType /* ofType */)
  538. {
  539.     return 0;
  540. }
  541.  
  542.  
  543. Boolean MAppleObject::CompareAppleObjects(DescType /* operation */,
  544.                                           const MAppleObject& /* toWhat */)
  545. {
  546.     return false;
  547. }
  548.  
  549.  
  550. void MAppleObject::DoAppleEvent(const AppleEvent& /* message */,
  551.                                 AppleEvent& /* reply */, long /* refCon */)
  552. {
  553.     FailOSErr(errAEEventNotHandled);
  554. }
  555.  
  556.  
  557. MAppleObject* MAppleObject::GetContainedObject(DescType /* desiredType */,
  558.                                                DescType /* keyForm */,
  559.                                                const AEDesc& /* keyData */,
  560.                                                Boolean& /* needDisposal */)
  561. {
  562.     return nil;
  563. }
  564.  
  565.  
  566. void MAppleObject::GotRequiredParameters(const AppleEvent& theAppleEvent)
  567. {
  568.     // look for the keyMissedKeywordAttr, just to see if it's there
  569.     DescType    returnedType;
  570.     Size        actualSize;
  571.     OSErr theErr = AEGetAttributePtr(&theAppleEvent, keyMissedKeywordAttr,
  572.                                      typeWildCard, &returnedType, nil, 0,
  573.                                      &actualSize);
  574.  
  575.     if (theErr == noErr)
  576.     {
  577.         // Since the attribute exists, we missed a parameter somewhere.
  578.         FailOSErr(errAEParamMissed);
  579.     }
  580.     else if (theErr != errAEDescNotFound)
  581.     {
  582.         // The only error that is OK is to say that the descriptor was not
  583.         // found (indicating that we got all the parameters).  If any other
  584.         // error occurred, throw it.
  585.         FailOSErr(theErr);
  586.     }
  587. }
  588.  
  589.  
  590. void MAppleObject::SetDefaultAppleObject(MAppleObject* defaultObject)
  591. {
  592.     fgDefaultAppleObject = defaultObject;
  593. }
  594.